home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
001-010
/
amok08
/
iff8svxload
/
iff8svxload.mod
< prev
next >
Wrap
Text File
|
1993-11-04
|
26KB
|
913 lines
(*---------------------------------------------------------------------------
:Program. IFF8SVXLoad.mod
:Author. Fridtjof Siebert
:Address. Nobileweg 67, D-7-Stgt-40
:Shortcut. [fbs]
:Version. .9
:Date. 18-Sep-88
:Copyright. PD, no commercial use !!!
:Language. Modula-II
:Translator. M2Amiga
:Imports. MemSystem [bne], Amok#5
:UpDate. none.
:Contents. Procedures to load and play sampled sounds.
:Remark. Contact me if you want to use this in your own commercial
:Remark. Software !
---------------------------------------------------------------------------*)
IMPLEMENTATION MODULE IFF8SVXLoad;
(*------------------------------ IMPORTs: -------------------------------*)
(*------ SYSTEM: ------*)
FROM SYSTEM IMPORT ADR, ADDRESS, LONGSET, SHIFT, CAST;
FROM Arts IMPORT Assert, TermProcedure, BreakPoint;
(*------ Libraries: ------*)
FROM Audio IMPORT IOAudioPtr, IOAudio, audioName, allocFailed, perVol;
FROM Dos IMPORT Open, Close, oldFile, Read, FileHandlePtr, Seek,
current;
FROM Exec IMPORT MsgPortPtr, DevicePtr, UByte, Byte, write, IOFlagSet,
ReplyMsg, GetMsg, OpenDevice, CopyMem, CloseDevice,
WaitPort, AddTask, RemTask, TaskPtr, Forbid, Permit,
NodeType, MsgPortAction, FindTask, Wait, Signal,
AllocSignal, FreeSignal;
FROM ExecSupport IMPORT CreatePort, DeletePort, NewList, BeginIO, AbortIO;
(*------ Standard: ------*)
FROM Strings IMPORT Compare, first, last;
(*------ Modules: ------*)
FROM MemSystem IMPORT ErrHeader, Allocate, AllocMem, Deallocate,
YesNoRequest, RETRY, CANCEL, ExitQuiet;
(*--------------------------- CONSTANTS: ----------------------------------
CONST
unity = 10000H; (* This is Fixed(1) = 1.0000H *)
sCompNone = 0; (* no compression *)
sCmpFibDelta = 1; (* Fibonacci-Delta encoding *)
(*----------------------------- TYPEs: ----------------------------------*)
TYPE
Fixed = LONGINT; (* Fixed Point Value (xxxx.xxxxH) *)
IFF8SVXChunks = (VHDR,NAME,COPY,AUTH,ANNO,ATAK,RLSE,BODY);
IFF8SVXChunkSet = SET OF IFF8SVXChunks;
(*------ Type for Data-Chunks: ------*)
DataChunkPtr = POINTER TO DataChunk;
DataChunk = RECORD
next: DataChunkPtr; (* to link them *)
prev: DataChunkPtr;
size: LONGCARD; (* size of this Chunk *)
data: ADDRESS; (* where to find it *)
END;
(*------ String: ------*)
String = ARRAY[0..999] OF CHAR;
(* This is used for smaller strings ! So don't modify them (insert sth.) ! *)
(*------ Type to contain loaded data: ------*)
IFF8SVXInfoPtr = POINTER TO IFF8SVXInfo;
IFF8SVXInfo = RECORD
loadedChunks: IFF8SVXChunkSet;
(* all Sub-RECORDs whose flag is set here contain legal data *)
next,prev: IFF8SVXInfoPtr;
(* unused. Can be used to link IFF8SVXInfo's *)
VHDR: RECORD (* 8SVX's header chunk *)
oneShotHiSamples: LONGCARD; (* # of Samples in shotpart Oct.1 *)
repeatHiSamples: LONGCARD; (* # of Repeatsamples in Oct. 1 *)
samplesPerHiCycle: LONGCARD; (* # Samples/Cycle or 0 *)
samplesPerSec: CARDINAL; (* Sampling-rate *)
countOctave: Byte; (* counts octaves *)
sCompression: Byte; (* Compression type or 0 if none *)
volume: Fixed; (* Volume (0..10000H) *)
END;
NAME: RECORD (* Sound's Name *)
size: LONGCARD; (* Length *)
string: POINTER TO String; (* Name *)
END;
COPY: RECORD (* Sound's CopyRight *)
size: LONGCARD;
string: POINTER TO String;
END;
AUTH: RECORD (* Sound's Author *)
size: LONGCARD;
string: POINTER TO String;
END;
ANNO: RECORD (* Author's Annotation *)
size: LONGCARD;
string: POINTER TO String;
END;
ATAK,RLSE: RECORD (* Attack & Decay duration *)
duration: CARDINAL; (* Duration in milliseconds *)
dest: Fixed; (* Destination Volume *)
END;
BODY: RECORD (* Data of sampled Voice *)
oneChunk: BOOLEAN; (* Just one Chunk per Octave ? *)
maxChunkSize: LONGCARD; (* Highest Chunk-Size *)
dataInChip: BOOLEAN; (* Chunks in Chip-Memory ? *)
soundData: ARRAY[0..7] OF DataChunkPtr;(* <= 8 Octaves of Data *)
END;
END;
(*------ Errors: ------*)
IFF8SVXErrs = (iff8OK,iff8OutOfMem,iff8Openfailed,iff8Readfailed,iff8NoIFF,
iff8NoChannel,iff8OpenDevicefailed);
(*--------------------------- Variables: --------------------------------*)
VAR
IFF8SVXError: IFF8SVXErrs; (* Last Error *)
--------------------------- internal Variables: -------------------------*)
TYPE
ExtIOAudio = RECORD
ioa: IOAudio;
id: CARDINAL;
END;
ExtIOAudioPtr = POINTER TO ExtIOAudio;
VAR
InH: FileHandlePtr;
Buffer: ADDRESS; (* Buffer for Reading / Writing *)
TextBuffer: POINTER TO ARRAY[0..63] OF ARRAY[0..3] OF CHAR;
LONGBuffer: POINTER TO ARRAY[0..63] OF LONGCARD;
WORDBuffer: POINTER TO ARRAY[0..127] OF CARDINAL;
LongPtr,LONGPtr: POINTER TO LONGCARD;
i,j: LONGCARD;
len: LONGCARD; (* number of bytes read from file *)
ChunkSize: LONGCARD; (* size of loaded octave *)
AllocPort: MsgPortPtr;
AllocIOB: IOAudioPtr;
Device: DevicePtr;
SoundPort: MsgPortPtr;
SoundIOB: IOAudioPtr;
AllocationMap: ARRAY[0..3] OF Byte;
SoundXIOA: ARRAY[0..3],[0..1] OF ExtIOAudioPtr;
SoundInfo: ARRAY[0..3] OF RECORD
info: IFF8SVXInfoPtr;
chunk: DataChunkPtr; (* active Chunk *)
oct: CARDINAL; (* octave to play *)
repCnt: CARDINAL; (* how often to repeat *)
bufSize: LONGCARD; (* size of Buffer *)
playing: BOOLEAN; (* playing or ready ? *)
done: BOOLEAN; (* sound played ? *)
dblBuf: BOOLEAN; (* DoubleBuffering ? *)
END;
ChannelDone: ARRAY[0..3] OF ExtIOAudioPtr;
PlayTask : TaskPtr;
PlayStack: ADDRESS;
SoundSignal: LONGINT;
SoundTask: TaskPtr;
(*------ Load an Octave: ------*)
PROCEDURE LoadChunk(Size,MaxSize: LONGCARD;
Prev: DataChunkPtr;
ChipMem: BOOLEAN): DataChunkPtr;
VAR
Chunk: DataChunkPtr;
BEGIN
Allocate(Chunk,SIZE(DataChunk));
IF Chunk=NIL THEN
IFF8SVXError := iff8OutOfMem;
RETURN NIL;
END;
WITH Chunk^ DO
prev := Prev;
IF (Size<=MaxSize) OR (MaxSize=0) THEN
size := Size;
ELSE
size := MaxSize;
END;
DEC(Size,size);
AllocMem(data,size,ChipMem);
IF data=NIL THEN
IFF8SVXError := iff8OutOfMem;
Deallocate(Chunk);
RETURN NIL;
END;
len := Read(InH,data,size);
IF len#size THEN
IFF8SVXError := iff8Readfailed;
Deallocate(data);
Deallocate(Chunk);
RETURN NIL;
END;
IF Size#0 THEN
next := LoadChunk(Size,MaxSize,Chunk,ChipMem);
IF next=NIL THEN
Deallocate(data);
Deallocate(Chunk);
RETURN NIL;
END;
ELSE
next := NIL;
END;
END; (* WITH Chunk^ DO *)
RETURN Chunk;
END LoadChunk;
(*-------------------------------------------------------------------------*)
(* *)
(* Load Sampled Sound: *)
(* *)
(*-------------------------------------------------------------------------*)
PROCEDURE Read8SVX(Name: ARRAY OF CHAR;
MaxChunkSize: LONGCARD;
ChipMem: BOOLEAN): IFF8SVXInfoPtr;
(* Name: Sound's Name *)
(* MaxChunkSize: MaxSize of Data-Chunk or 0 to load to a single chunk *)
(* ChipMem: TRUE if you want all chunks in ChipMem. *)
(* Resul: Pointer to info of loaded sample or NIL if any error *)
(* occured. IFF8SVXError contains errortype. *)
VAR
Info: IFF8SVXInfoPtr;
BEGIN
IFF8SVXError := iff8OK;
Allocate(Info,SIZE(Info^));
IF Info=NIL THEN
IFF8SVXError := iff8OutOfMem;
RETURN NIL;
END;
(*------ Open File: ------*)
LOOP
InH := Open(ADR(Name),oldFile);
IF InH=NIL THEN
IFF8SVXError := iff8Openfailed;
EXIT;
END;
(*------ File Header: ------*)
len := Read(InH,Buffer,12);
IF len=0 THEN
IFF8SVXError := iff8Readfailed;
EXIT;
END;
IF (Compare(TextBuffer^[0],first,4,"FORM",TRUE)#0) OR
(Compare(TextBuffer^[2],first,4,"8SVX",TRUE)#0) THEN
IFF8SVXError := iff8NoIFF;
EXIT;
END;
(*------ Main Loop: ------*)
LOOP
len := Read(InH,Buffer,8);
IF len#8 THEN
IFF8SVXError := iff8Readfailed;
EXIT;
END;
(*------ VHDR: ------*)
IF Compare(TextBuffer^[0],first,4,"VHDR",TRUE)=0 THEN
INCL(Info^.loadedChunks,VHDR);
len := Read(InH,Buffer,LONGBuffer^[1]);
LONGPtr := Buffer;
LongPtr := ADR(Info^.VHDR);
FOR i:=0 TO 4 DO
LongPtr^ := LONGPtr^;
INC(LongPtr,4);
INC(LONGPtr,4);
END;
(*------ NAME: ------*)
ELSIF Compare(TextBuffer^[0],first,4,"NAME",TRUE)=0 THEN
INCL(Info^.loadedChunks,NAME);
WITH Info^.NAME DO
size := LONGBuffer^[1]+1;
AllocMem(string,size,TRUE);
IF string=NIL THEN IFF8SVXError := iff8OutOfMem; EXIT END;
len := Read(InH,string,size-1);
IF ODD(size-1) THEN len := Read(InH,Buffer,1) END;
END;
(*------ COPY: ------*)
ELSIF Compare(TextBuffer^[0],first,4,"(c) ",TRUE)=0 THEN
INCL(Info^.loadedChunks,COPY);
WITH Info^.COPY DO
size := LONGBuffer^[1]+1;
AllocMem(string,size,TRUE);
IF string=NIL THEN IFF8SVXError := iff8OutOfMem; EXIT END;
len := Read(InH,string,size-1);
IF ODD(size-1) THEN len := Read(InH,Buffer,1) END;
END;
(*------ AUTH: ------*)
ELSIF Compare(TextBuffer^[0],first,4,"AUTH",TRUE)=0 THEN
INCL(Info^.loadedChunks,AUTH);
WITH Info^.AUTH DO
size := LONGBuffer^[1]+1;
AllocMem(string,size,TRUE);
IF string=NIL THEN IFF8SVXError := iff8OutOfMem; EXIT END;
len := Read(InH,string,size-1);
IF ODD(size-1) THEN len := Read(InH,Buffer,1) END;
END;
(*------ ANNO: ------*)
ELSIF Compare(TextBuffer^[0],first,4,"ANNO",TRUE)=0 THEN
INCL(Info^.loadedChunks,ANNO);
WITH Info^.ANNO DO
size := LONGBuffer^[1]+1;
AllocMem(string,size,TRUE);
IF string=NIL THEN IFF8SVXError := iff8OutOfMem; EXIT END;
len := Read(InH,string,size-1);
IF ODD(size-1) THEN len := Read(InH,Buffer,1) END;
END;
(*------ ATAK: ------*)
ELSIF Compare(TextBuffer^[0],first,4,"ATAK",TRUE)=0 THEN
INCL(Info^.loadedChunks,ATAK);
len := Read(InH,Buffer,LONGBuffer^[1]);
Info^.ATAK.duration := WORDBuffer^[0];
LONGPtr := ADDRESS(LONGCARD(Buffer) + 2);
Info^.ATAK.dest := LONGPtr^;
(*------ RLSE: ------*)
ELSIF Compare(TextBuffer^[0],first,4,"RLSE",TRUE)=0 THEN
INCL(Info^.loadedChunks,RLSE);
len := Read(InH,Buffer,LONGBuffer^[1]);
Info^.RLSE.duration := WORDBuffer^[0];
LONGPtr := ADDRESS(LONGCARD(Buffer) + 2);
Info^.RLSE.dest := LONGPtr^;
(*------ BODY: ------*)
ELSIF Compare(TextBuffer^[0],first,4,"BODY",TRUE)=0 THEN
IF NOT(VHDR IN Info^.loadedChunks) THEN
IFF8SVXError := iff8NoIFF;
EXIT;
END;
INCL(Info^.loadedChunks,BODY);
WITH Info^.BODY DO
oneChunk := TRUE;
dataInChip := ChipMem;
WITH Info^.VHDR DO
ChunkSize := oneShotHiSamples + repeatHiSamples;
FOR i:=0 TO Info^.VHDR.countOctave-1 DO
soundData[i] := LoadChunk(ChunkSize,MaxChunkSize,NIL,ChipMem);
IF soundData[i]=NIL THEN EXIT END;
maxChunkSize := ChunkSize;
INC(ChunkSize,ChunkSize);
END;
IF maxChunkSize>MaxChunkSize THEN
maxChunkSize := MaxChunkSize;
END;
END;
END;
EXIT;
(*------ Unknown Chunk: ------*)
ELSE
IF ODD(LONGBuffer^[1]) THEN
len := Seek(InH,current,LONGBuffer^[1]+1);
ELSE
len := Seek(InH,current,LONGBuffer^[1]);
END;
END;
END; (* LOOP *)
(*------ EXIT & Error check: ------*)
IF NOT((VHDR IN Info^.loadedChunks) OR (BODY IN Info^.loadedChunks)) THEN
IFF8SVXError := iff8NoIFF;
END;
EXIT;
END; (* LOOP *)
IF IFF8SVXError#iff8OK THEN
Dealloc8SVX(Info);
Info := NIL;
END;
Close(InH); InH := NIL;
RETURN Info;
END Read8SVX;
(*------ Free DataChunk's Memory: ------*)
PROCEDURE FreeChunks(first: DataChunkPtr);
BEGIN
WITH first^ DO
IF next#NIL THEN FreeChunks(next) END;
IF data#NIL THEN
Deallocate(data);
END;
END;
Deallocate(first);
END FreeChunks;
(*-------------------------------------------------------------------------*)
(* *)
(* Free Sound's Memory: *)
(* *)
(*-------------------------------------------------------------------------*)
PROCEDURE Dealloc8SVX(Info:IFF8SVXInfoPtr);
(* Info: Sound's Info-Record *)
VAR
i: CARDINAL;
BEGIN
IF Info#NIL THEN
IF NAME IN Info^.loadedChunks THEN
WITH Info^.NAME DO
IF string#NIL THEN Deallocate(string) END;
END;
END;
IF COPY IN Info^.loadedChunks THEN
WITH Info^.COPY DO
IF string#NIL THEN Deallocate(string) END;
END;
END;
IF AUTH IN Info^.loadedChunks THEN
WITH Info^.AUTH DO
IF string#NIL THEN Deallocate(string) END;
END;
END;
IF ANNO IN Info^.loadedChunks THEN
WITH Info^.ANNO DO
IF string#NIL THEN Deallocate(string) END;
END;
END;
IF BODY IN Info^.loadedChunks THEN
FOR i:=0 TO Info^.VHDR.countOctave-1 DO
IF Info^.BODY.soundData[i]#NIL THEN
FreeChunks(Info^.BODY.soundData[i]);
END;
END;
END;
Deallocate(Info);
END;
END Dealloc8SVX;
(*------ Task to play Sound: ------*)
PROCEDURE PlayTaskProc(); (* $S- *)
VAR
XIOA: ExtIOAudioPtr;
i: CARDINAL;
BEGIN
LOOP
WaitPort(SoundPort);
XIOA := GetMsg(SoundPort);
IF (XIOA#NIL) AND (XIOA^.ioa.request.error=0) THEN
WITH SoundInfo[XIOA^.id] DO
Forbid();
IF done THEN
ChannelDone[XIOA^.id] := NIL;
END;
IF playing THEN
IF chunk^.next#NIL THEN
chunk := chunk^.next;
ELSIF repCnt>1 THEN
DEC(repCnt);
chunk := info^.BODY.soundData[oct];
ELSE
done := TRUE;
ChannelDone[XIOA^.id] := XIOA;
playing := FALSE;
Signal(SoundTask,LONGSET{SoundSignal})
END;
END;
IF NOT(done) THEN
playing := TRUE;
IF dblBuf THEN
CopyMem(chunk^.data,XIOA^.ioa.data,chunk^.size);
ELSE
XIOA^.ioa.data := chunk^.data;
END;
XIOA^.ioa.length := chunk^.size;
BeginIO(XIOA);
END;
Permit();
END; (* WITH SoundInfo[XIOA^.id] *)
END; (* IF Msg ok THEN *)
END; (* endless LOOP *)
END PlayTaskProc;
(*-------------------------------------------------------------------------*)
(* *)
(* Open Audio Device: *)
(* *)
(*-------------------------------------------------------------------------*)
PROCEDURE OpenAudio(Channels: CARDINAL; Priority: Byte): BOOLEAN;
(* Channels: Number of soundchannels to allocate *)
(* Prioriy: Allocation Priority *)
BEGIN
IFF8SVXError := iff8OK;
(*------ Allocation Precedence and Channel: ------*)
AllocIOB^.request.message.node.pri := -40;
AllocIOB^.request.message.replyPort:= AllocPort;
CASE Channels OF
1: AllocationMap[0] := 1;
AllocationMap[1] := 2;
AllocationMap[2] := 4;
AllocationMap[3] := 8; |
2: AllocationMap[0] := 3;
AllocationMap[1] := 6;
AllocationMap[2] := 12;
AllocationMap[3] := 5; |
3: AllocationMap[0] := 14;
AllocationMap[1] := 13;
AllocationMap[2] := 11;
AllocationMap[3] := 7; |
4: AllocationMap[0] := 15;
AllocationMap[1] := 15;
AllocationMap[2] := 15;
AllocationMap[3] := 15; |
END;
AllocIOB^.data := ADR(AllocationMap);
AllocIOB^.length := SIZE(AllocationMap);
(*------ Open Audio-Device: ------*)
OpenDevice(ADR(audioName),0,AllocIOB,LONGSET{});
(* Why doesn't OpenDevice() return it's error ??? *)
CASE AllocIOB^.request.error OF
-1,allocFailed:
IFF8SVXError := iff8OpenDevicefailed;
RETURN FALSE |
ELSE
END;
Device := AllocIOB^.request.device;
(*------ Initialize ReplyPort: ------*)
WITH SoundPort^ DO
flags := signal;
node.type := msgPort;
END;
NewList(ADR(SoundPort^.msgList));
(*------ Initialize I/O-Block: ------*)
j := 0;
FOR i:=0 TO 3 DO
WITH SoundXIOA[i,0]^ DO
id := i;
ioa.request.message.replyPort := SoundPort;
ioa.request.device := Device;
WHILE (j<4) AND NOT(j IN CAST(LONGSET,AllocIOB^.request.unit)) DO
INC(j);
END;
IF j<4 THEN
ioa.request.unit := CAST(ADDRESS,LONGSET{j});
DEC(Channels,1);
ELSE
ioa.request.unit := NIL;
END;
INC(j);
ioa.request.command := write;
ioa.request.flags := IOFlagSet{4}; (* perVol *)
ioa.allocKey := AllocIOB^.allocKey;
END;
SoundXIOA[i,1]^ := SoundXIOA[i,0]^;
SoundInfo[i].playing := FALSE;
SoundInfo[i].done := TRUE;
ChannelDone[i] := NIL;
END;
(*------ Start PlayTask: ------*)
Allocate(PlayTask,SIZE(PlayTask^));
IF PlayTask=NIL THEN ExitQuiet END;
SoundPort^.sigTask := PlayTask;
WITH PlayTask^ DO
spLower := PlayStack;
spUpper := ADDRESS(LONGCARD(PlayStack) + 1000);
spReg := spUpper;
node.type := task;
node.name := ADR("SamplePlayTask");
END;
AddTask(PlayTask,ADR(PlayTaskProc),NIL);
IF Channels>0 THEN
CloseAudio();
IFF8SVXError := iff8NoChannel;
RETURN FALSE;
END;
RETURN TRUE;
END OpenAudio;
(*-------------------------------------------------------------------------*)
(* *)
(* Close Audio Device: *)
(* *)
(*-------------------------------------------------------------------------*)
PROCEDURE CloseAudio();
BEGIN
RemTask(PlayTask);
Deallocate(PlayTask);
PlayTask := NIL;
CloseDevice(AllocIOB);
Device := NIL;
FOR i:=0 TO 3 DO
IF SoundInfo[i].dblBuf THEN
WITH SoundXIOA[i,0]^.ioa DO
IF data#NIL THEN Deallocate(data) END;
END;
WITH SoundXIOA[i,1]^.ioa DO
IF data#NIL THEN Deallocate(data) END;
END;
END;
END;
END CloseAudio;
(*-------------------------------------------------------------------------*)
(* *)
(* Play sampled Sound: *)
(* *)
(*-------------------------------------------------------------------------*)
PROCEDURE PlaySample(Info: IFF8SVXInfoPtr;
Octave: INTEGER;
Repeat: CARDINAL;
Channel: CARDINAL): BOOLEAN;
(* Info: Sound's IFF8SVXInfo *)
(* Octave: Octave to play (0..7) *)
(* Repeat: how often to repeat sound *)
(* Channel: Channel to play sound *)
VAR
Reply: BOOLEAN;
(*------ Fun Starts: ------*)
BEGIN
IF Info=NIL THEN
IFF8SVXError := iff8NoIFF;
RETURN FALSE;
END;
IF Octave >= Info^.VHDR.countOctave THEN RETURN TRUE END;
WITH SoundInfo[Channel] DO
Forbid();
Reply := done;
AbortIO(SoundXIOA[Channel,0]);
AbortIO(SoundXIOA[Channel,1]);
WITH Info^ DO
info := Info;
chunk := BODY.soundData[Octave];
oct := Octave;
repCnt := Repeat;
playing := FALSE;
done := FALSE;
bufSize := Info^.BODY.maxChunkSize;
IF dblBuf THEN
FOR i:=0 TO 1 DO
WITH SoundXIOA[Channel,i]^.ioa DO
IF data#NIL THEN Deallocate(data) END;
END;
END;
END;
dblBuf := NOT(BODY.dataInChip);
FOR i:=0 TO 1 DO;
WITH SoundXIOA[Channel,i]^.ioa DO
period := LONGINT(3584200) DIV LONGINT(VHDR.samplesPerSec);
volume := SHIFT(VHDR.volume,-10);
cycles := 1;
IF dblBuf THEN
AllocMem(data,bufSize,TRUE);
IF data=NIL THEN
IFF8SVXError := iff8OutOfMem;
RETURN FALSE;
END;
ELSE
data := NIL;
END;
END;
END;
IF Reply THEN
IF ChannelDone[Channel] = NIL THEN
ReplyMsg(SoundXIOA[Channel,0]);
ReplyMsg(SoundXIOA[Channel,1]);
ELSE
ReplyMsg(ChannelDone[Channel]);
END;
END;
END;
Permit();
END;
IFF8SVXError := iff8OK;
RETURN TRUE;
END PlaySample;
(*-------------------------------------------------------------------------*)
(* *)
(* Wait for Play to finish: *)
(* *)
(*-------------------------------------------------------------------------*)
(*
CONST
AllChannels = 4;
*)
PROCEDURE WaitPlay(Channel: CARDINAL);
(* This waits for a channel to complete. *)
(* WaitPlay(AllChannels) waits for all channels to finish. *)
VAR
i: CARDINAL;
x: BOOLEAN;
BEGIN
IF Channel<AllChannels THEN
IF NOT(SoundInfo[Channel].done) THEN
IF Wait(LONGSET{SoundSignal})=LONGSET{} THEN END;
END;
ELSE
LOOP
x := TRUE;
FOR i:=0 TO 3 DO
x := x AND SoundInfo[i].done;
END;
IF x THEN EXIT END;
IF Wait(LONGSET{SoundSignal})=LONGSET{} THEN END;
END;
END;
END WaitPlay;
(*------ CleanUp: ------*)
PROCEDURE CleanUp();
BEGIN
IF PlayTask #NIL THEN
RemTask(PlayTask);
Deallocate(PlayTask);
END;
IF Device#NIL THEN CloseDevice(AllocIOB) END;
IF Buffer#NIL THEN Deallocate(Buffer) END;
IF InH#NIL THEN Close(InH) END;
IF AllocIOB #NIL THEN Deallocate(AllocIOB ) END;
IF AllocPort#NIL THEN DeletePort(AllocPort) END;
IF SoundPort#NIL THEN Deallocate(SoundPort) END;
IF PlayStack#NIL THEN Deallocate(PlayStack) END;
FOR i:=0 TO 3 DO
IF SoundInfo[i].dblBuf THEN
WITH SoundXIOA[i,0]^.ioa DO
IF data#NIL THEN Deallocate(data) END;
END;
WITH SoundXIOA[i,1]^.ioa DO
IF data#NIL THEN Deallocate(data) END;
END;
END;
IF SoundXIOA[i,0]#NIL THEN Deallocate(SoundXIOA[i,0]) END;
IF SoundXIOA[i,1]#NIL THEN Deallocate(SoundXIOA[i,1]) END;
END;
FreeSignal(SoundSignal);
END CleanUp;
(*------------------------- Initialization: -----------------------------*)
BEGIN
ErrHeader := "Error loading Sampled Sound:";
AllocMem(Buffer,768,TRUE);
Assert(Buffer#NIL,ADR("Not enough ChipMem !!!"));
TextBuffer := Buffer;
LONGBuffer := Buffer;
WORDBuffer := Buffer;
InH := NIL;
AllocPort := CreatePort(ADR("Sampled SoundPort"),0);
IF AllocPort=NIL THEN ExitQuiet END;
Allocate(AllocIOB,SIZE(AllocIOB^));
IF AllocPort=NIL THEN ExitQuiet END;
FOR i:=0 TO 3 DO
Allocate(SoundXIOA[i,0],SIZE(ExtIOAudio));
IF SoundXIOA[i,0]=NIL THEN ExitQuiet END;
Allocate(SoundXIOA[i,1],SIZE(ExtIOAudio));
IF SoundXIOA[i,1]=NIL THEN ExitQuiet END;
SoundInfo[i].dblBuf := FALSE;
SoundInfo[i].done := TRUE;
END;
Allocate(SoundPort,SIZE(SoundPort^));
IF SoundPort=NIL THEN ExitQuiet END;
Allocate(PlayStack,1000);
IF PlayStack=NIL THEN ExitQuiet END;
PlayTask := NIL;
SoundSignal := AllocSignal(-1);
Assert(SoundSignal>0,ADR("No more Signalbits !!!"));
SoundTask := FindTask(0);
Device := NIL;
TermProcedure(CleanUp);
END IFF8SVXLoad.